home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / share / system-config-printer / monitor.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-10-28  |  20KB  |  743 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. import cups
  5. cups.require('1.9.42')
  6. import dbus
  7. import dbus.glib as dbus
  8. import gobject
  9. import time
  10. from debug import *
  11. import pprint
  12.  
  13. _ = lambda x: x
  14.  
  15. def set_gettext_function(x):
  16.     _ = x
  17.  
  18. import statereason
  19. from statereason import StateReason
  20. statereason.set_gettext_function(_)
  21. CONNECTING_TIMEOUT = 60
  22. MIN_REFRESH_INTERVAL = 1
  23.  
  24. def state_reason_is_harmless(reason):
  25.     if reason.startswith('moving-to-paused') and reason.startswith('paused') and reason.startswith('shutdown') and reason.startswith('stopping') or reason.startswith('stopped-partly'):
  26.         return True
  27.     return False
  28.  
  29.  
  30. def collect_printer_state_reasons(connection):
  31.     result = { }
  32.     
  33.     try:
  34.         printers = connection.getPrinters()
  35.     except cups.IPPError:
  36.         return result
  37.  
  38.     for name, printer in printers.iteritems():
  39.         reasons = printer['printer-state-reasons']
  40.         for reason in reasons:
  41.             if reason == 'none':
  42.                 break
  43.             
  44.             if state_reason_is_harmless(reason):
  45.                 continue
  46.             
  47.             if not result.has_key(name):
  48.                 result[name] = []
  49.             
  50.             result[name].append(StateReason(name, reason))
  51.         
  52.     
  53.     return result
  54.  
  55.  
  56. class Watcher:
  57.     
  58.     def monitor_exited(self, monitor):
  59.         debugprint(repr(monitor) + ' exited')
  60.  
  61.     
  62.     def state_reason_added(self, monitor, reason):
  63.         debugprint(repr(monitor) + ': +' + repr(reason))
  64.  
  65.     
  66.     def state_reason_removed(self, monitor, reason):
  67.         debugprint(repr(monitor) + ': -' + repr(reason))
  68.  
  69.     
  70.     def still_connecting(self, monitor, reason):
  71.         debugprint(repr(monitor) + ": `%s' still connecting" % reason.get_printer())
  72.  
  73.     
  74.     def now_connected(self, monitor, printer):
  75.         debugprint(repr(monitor) + ": `%s' now connected" % printer)
  76.  
  77.     
  78.     def current_printers_and_jobs(self, monitor, printers, jobs):
  79.         debugprint(repr(monitor) + ': printers and jobs lists provided')
  80.  
  81.     
  82.     def job_added(self, monitor, jobid, eventname, event, jobdata):
  83.         debugprint(repr(monitor) + ': job %d added' % jobid)
  84.  
  85.     
  86.     def job_event(self, monitor, jobid, eventname, event, jobdata):
  87.         debugprint(repr(monitor) + ": job %d has event `%s'" % (jobid, eventname))
  88.  
  89.     
  90.     def job_removed(self, monitor, jobid, eventname, event):
  91.         debugprint(repr(monitor) + ': job %d removed' % jobid)
  92.  
  93.     
  94.     def printer_added(self, monitor, printer):
  95.         debugprint(repr(monitor) + ": printer `%s' added" % printer)
  96.  
  97.     
  98.     def printer_event(self, monitor, printer, eventname, event):
  99.         debugprint(repr(monitor) + ": printer `%s' has event `%s'" % (printer, eventname))
  100.  
  101.     
  102.     def printer_removed(self, monitor, printer):
  103.         debugprint(repr(monitor) + ": printer `%s' removed" % printer)
  104.  
  105.     
  106.     def cups_connection_error(self, monitor):
  107.         debugprint(repr(monitor) + ': CUPS connection error')
  108.  
  109.     
  110.     def cups_ipp_error(self, monitor, e, m):
  111.         debugprint(repr(monitor) + ': CUPS IPP error (%d, %s)' % (e, repr(m)))
  112.  
  113.  
  114.  
  115. class Monitor:
  116.     DBUS_PATH = '/com/redhat/PrinterSpooler'
  117.     DBUS_IFACE = 'com.redhat.PrinterSpooler'
  118.     
  119.     def __init__(self, watcher, bus = None, my_jobs = True, specific_dests = None, monitor_jobs = True, host = None, port = None, encryption = None):
  120.         self.watcher = watcher
  121.         self.my_jobs = my_jobs
  122.         self.specific_dests = specific_dests
  123.         self.monitor_jobs = monitor_jobs
  124.         self.jobs = { }
  125.         self.printer_state_reasons = { }
  126.         self.printers = set()
  127.         self.process_pending_events = True
  128.         self.fetch_jobs_timer = None
  129.         if host:
  130.             cups.setServer(host)
  131.         
  132.         if port:
  133.             cups.setPort(port)
  134.         
  135.         if encryption:
  136.             cups.setEncryption(encryption)
  137.         
  138.         self.user = cups.getUser()
  139.         self.host = cups.getServer()
  140.         self.port = cups.getPort()
  141.         self.encryption = cups.getEncryption()
  142.         self.which_jobs = 'not-completed'
  143.         self.reasons_seen = { }
  144.         self.connecting_timers = { }
  145.         self.still_connecting = set()
  146.         self.connecting_to_device = { }
  147.         self.received_any_dbus_signals = False
  148.         self.update_timer = None
  149.         if bus == None:
  150.             
  151.             try:
  152.                 bus = dbus.SystemBus()
  153.             except dbus.exceptions.DBusException:
  154.                 pass
  155.             except:
  156.                 None<EXCEPTION MATCH>dbus.exceptions.DBusException
  157.             
  158.  
  159.         None<EXCEPTION MATCH>dbus.exceptions.DBusException
  160.         if bus != None:
  161.             bus.add_signal_receiver(self.handle_dbus_signal, path = self.DBUS_PATH, dbus_interface = self.DBUS_IFACE)
  162.             self.bus = bus
  163.         
  164.         self.sub_id = -1
  165.         self.refresh()
  166.  
  167.     
  168.     def get_jobs(self):
  169.         return self.jobs.copy()
  170.  
  171.     
  172.     def cleanup(self):
  173.         if self.sub_id != -1:
  174.             user = cups.getUser()
  175.             
  176.             try:
  177.                 cups.setUser(self.user)
  178.                 c = cups.Connection(host = self.host, port = self.port, encryption = self.encryption)
  179.                 c.cancelSubscription(self.sub_id)
  180.                 debugprint('Canceled subscription %d' % self.sub_id)
  181.             except:
  182.                 pass
  183.  
  184.             cups.setUser(user)
  185.         
  186.         if self.bus != None:
  187.             self.bus.remove_signal_receiver(self.handle_dbus_signal, path = self.DBUS_PATH, dbus_interface = self.DBUS_IFACE)
  188.         
  189.         timers = self.connecting_timers.values()
  190.         for timer in [
  191.             self.update_timer,
  192.             self.fetch_jobs_timer]:
  193.             if timer:
  194.                 timers.append(timer)
  195.                 continue
  196.         
  197.         for timer in timers:
  198.             gobject.source_remove(timer)
  199.         
  200.         self.watcher.monitor_exited(self)
  201.  
  202.     
  203.     def set_process_pending(self, whether):
  204.         self.process_pending_events = whether
  205.  
  206.     
  207.     def check_still_connecting(self, printer):
  208.         '''Timer callback to check on connecting-to-device reasons.'''
  209.         if not self.process_pending_events:
  210.             timer = gobject.timeout_add(200, self.check_still_connecting, printer)
  211.             self.connecting_timers[printer] = timer
  212.             return False
  213.         del self.connecting_timers[printer]
  214.         debugprint("Still-connecting timer fired for `%s'" % printer)
  215.         (printer_jobs, my_printers) = self.sort_jobs_by_printer()
  216.         self.update_connecting_devices(printer_jobs)
  217.         return False
  218.  
  219.     
  220.     def update_connecting_devices(self, printer_jobs = { }):
  221.         '''Updates connecting_to_device dict and still_connecting set.'''
  222.         time_now = time.time()
  223.         connecting_to_device = { }
  224.         trouble = False
  225.         for printer, reasons in self.printer_state_reasons.iteritems():
  226.             connected = True
  227.             for reason in reasons:
  228.                 if reason.get_reason() == 'connecting-to-device':
  229.                     have_processing_job = False
  230.                     for job, data in printer_jobs.get(printer, { }).iteritems():
  231.                         state = data.get('job-state', cups.IPP_JOB_CANCELED)
  232.                         if state == cups.IPP_JOB_PROCESSING:
  233.                             have_processing_job = True
  234.                             break
  235.                             continue
  236.                     
  237.                     if not have_processing_job:
  238.                         debugprint('Ignoring stale connecting-to-device x')
  239.                         continue
  240.                     
  241.                     printer = reason.get_printer()
  242.                     t = self.connecting_to_device.get(printer, time_now)
  243.                     connecting_to_device[printer] = t
  244.                     debugprint('Connecting time: %d' % (time_now - t))
  245.                     if time_now - t >= CONNECTING_TIMEOUT:
  246.                         if have_processing_job:
  247.                             if printer not in self.still_connecting:
  248.                                 self.still_connecting.add(printer)
  249.                                 self.watcher.still_connecting(self, reason)
  250.                             
  251.                             if self.connecting_timers.has_key(printer):
  252.                                 gobject.source_remove(self.connecting_timers[printer])
  253.                                 del self.connecting_timers[printer]
  254.                                 debugprint("Stopped connecting timer for `%s'" % printer)
  255.                             
  256.                         
  257.                     
  258.                     connected = False
  259.                     break
  260.                     continue
  261.             
  262.             if connected and self.connecting_timers.has_key(printer):
  263.                 gobject.source_remove(self.connecting_timers[printer])
  264.                 del self.connecting_timers[printer]
  265.                 debugprint("Stopped connecting timer for `%s'" % printer)
  266.                 continue
  267.         
  268.         remove = set()
  269.         for printer in self.still_connecting:
  270.             if not connecting_to_device.has_key(printer):
  271.                 remove.add(printer)
  272.                 self.watcher.now_connected(self, printer)
  273.                 if self.connecting_timers.has_key(printer):
  274.                     gobject.source_remove(self.connecting_timers[printer])
  275.                     del self.connecting_timers[printer]
  276.                     debugprint("Stopped connecting timer for `%s'" % printer)
  277.                 
  278.             self.connecting_timers.has_key(printer)
  279.         
  280.         self.still_connecting = self.still_connecting.difference(remove)
  281.         self.connecting_to_device = connecting_to_device
  282.  
  283.     
  284.     def check_state_reasons(self, my_printers = set(), printer_jobs = { }):
  285.         old_reasons_seen_keys = self.reasons_seen.keys()
  286.         reasons_now = set()
  287.         for printer, reasons in self.printer_state_reasons.iteritems():
  288.             for reason in reasons:
  289.                 tuple = reason.get_tuple()
  290.                 printer = reason.get_printer()
  291.                 reasons_now.add(tuple)
  292.                 if not self.reasons_seen.has_key(tuple):
  293.                     self.watcher.state_reason_added(self, reason)
  294.                     self.reasons_seen[tuple] = reason
  295.                 
  296.                 if reason.get_reason() == 'connecting-to-device' and not self.connecting_to_device.has_key(printer):
  297.                     have_processing_job = False
  298.                     for job, data in printer_jobs.get(printer, { }).iteritems():
  299.                         state = data.get('job-state', cups.IPP_JOB_CANCELED)
  300.                         if state == cups.IPP_JOB_PROCESSING:
  301.                             have_processing_job = True
  302.                             break
  303.                             continue
  304.                     
  305.                 None if have_processing_job else get_debugging()
  306.             
  307.         
  308.         self.update_connecting_devices(printer_jobs)
  309.         items = self.reasons_seen.keys()
  310.         for tuple in items:
  311.             if tuple not in reasons_now:
  312.                 reason = self.reasons_seen[tuple]
  313.                 del self.reasons_seen[tuple]
  314.                 self.watcher.state_reason_removed(self, reason)
  315.                 continue
  316.         
  317.  
  318.     
  319.     def get_notifications(self):
  320.         if not self.process_pending_events:
  321.             if self.update_timer:
  322.                 gobject.source_remove(self.update_timer)
  323.             
  324.             self.update_timer = gobject.timeout_add(200, self.get_notifications)
  325.             return False
  326.         debugprint('get_notifications')
  327.         user = cups.getUser()
  328.         
  329.         try:
  330.             cups.setUser(self.user)
  331.             c = cups.Connection(host = self.host, port = self.port, encryption = self.encryption)
  332.             
  333.             try:
  334.                 
  335.                 try:
  336.                     notifications = c.getNotifications([
  337.                         self.sub_id], [
  338.                         self.sub_seq + 1])
  339.                 except AttributeError:
  340.                     self.process_pending_events
  341.                     self.process_pending_events
  342.                     notifications = c.getNotifications([
  343.                         self.sub_id])
  344.                 except:
  345.                     self.process_pending_events
  346.  
  347.             except cups.IPPError:
  348.                 self.process_pending_events
  349.                 (e, m) = self.process_pending_events
  350.                 cups.setUser(user)
  351.                 if e == cups.IPP_NOT_FOUND:
  352.                     self.sub_id = -1
  353.                     self.refresh()
  354.                     return False
  355.                 self.watcher.cups_ipp_error(self, e, m)
  356.                 return True
  357.                 e == cups.IPP_NOT_FOUND
  358.  
  359.         except RuntimeError:
  360.             self.process_pending_events
  361.             self.process_pending_events
  362.             cups.setUser(user)
  363.             self.watcher.cups_connection_error(self)
  364.             return True
  365.  
  366.         cups.setUser(user)
  367.         deferred_calls = []
  368.         jobs = self.jobs.copy()
  369.         for event in notifications['events']:
  370.             seq = event['notify-sequence-number']
  371.             self.sub_seq = seq
  372.             nse = event['notify-subscribed-event']
  373.             debugprint('%d %s %s' % (seq, nse, event['notify-text']))
  374.             if get_debugging():
  375.                 debugprint(pprint.pformat(event))
  376.             
  377.             if nse.startswith('printer-'):
  378.                 name = event['printer-name']
  379.                 if nse == 'printer-added' and name not in self.printers:
  380.                     self.printers.add(name)
  381.                     deferred_calls.append((self.watcher.printer_added, (self, name)))
  382.                     continue
  383.                 if nse == 'printer-deleted' and name in self.printers:
  384.                     self.printers.remove(name)
  385.                     items = self.reasons_seen.keys()
  386.                     for tuple in items:
  387.                         if tuple[1] == name:
  388.                             reason = self.reasons_seen[tuple]
  389.                             del self.reasons_seen[tuple]
  390.                             deferred_calls.append((self.watcher.state_reason_removed, (self, reason)))
  391.                             continue
  392.                     
  393.                     if self.printer_state_reasons.has_key(name):
  394.                         del self.printer_state_reasons[name]
  395.                     
  396.                     deferred_calls.append((self.watcher.printer_removed, (self, name)))
  397.                     continue
  398.                 if name in self.printers:
  399.                     printer_state_reasons = event['printer-state-reasons']
  400.                     reasons = []
  401.                     for reason in printer_state_reasons:
  402.                         if reason == 'none':
  403.                             break
  404.                         
  405.                         if state_reason_is_harmless(reason):
  406.                             continue
  407.                         
  408.                         reasons.append(StateReason(name, reason))
  409.                     
  410.                     self.printer_state_reasons[name] = reasons
  411.                     deferred_calls.append((self.watcher.printer_event, (self, name, nse, event)))
  412.                     continue
  413.                 continue
  414.             
  415.             jobid = event['notify-job-id']
  416.             if (nse == 'job-created' or nse == 'job-state-changed') and not jobs.has_key(jobid) and event['job-state'] == cups.IPP_JOB_PROCESSING:
  417.                 if self.specific_dests != None and event['printer-name'] not in self.specific_dests:
  418.                     continue
  419.                 
  420.                 
  421.                 try:
  422.                     attrs = c.getJobAttributes(jobid)
  423.                     if self.my_jobs and attrs['job-originating-user-name'] != cups.getUser():
  424.                         continue
  425.                     
  426.                     jobs[jobid] = attrs
  427.                 except AttributeError:
  428.                     jobs[jobid] = {
  429.                         'job-k-octets': 0 }
  430.                 except cups.IPPError:
  431.                     (e, m) = None
  432.                     self.watcher.cups_ipp_error(self, e, m)
  433.                     jobs[jobid] = {
  434.                         'job-k-octets': 0 }
  435.  
  436.                 deferred_calls.append((self.watcher.job_added, (self, jobid, nse, event, jobs[jobid].copy())))
  437.             elif (nse == 'job-completed' or nse == 'job-state-changed') and event['job-state'] == cups.IPP_JOB_COMPLETED:
  438.                 if self.which_jobs not in ('completed', 'all'):
  439.                     
  440.                     try:
  441.                         del jobs[jobid]
  442.                         deferred_calls.append((self.watcher.job_removed, (self, jobid, nse, event)))
  443.                     continue
  444.                     except KeyError:
  445.                         continue
  446.                     
  447.  
  448.                 
  449.             
  450.             
  451.             try:
  452.                 job = jobs[jobid]
  453.             except KeyError:
  454.                 continue
  455.  
  456.             for attribute in [
  457.                 'job-state',
  458.                 'job-name']:
  459.                 job[attribute] = event[attribute]
  460.             
  461.             if event.has_key('notify-printer-uri'):
  462.                 job['job-printer-uri'] = event['notify-printer-uri']
  463.             
  464.             deferred_calls.append((self.watcher.job_event, (self, jobid, nse, event, job.copy())))
  465.         
  466.         self.set_process_pending(False)
  467.         self.update_jobs(jobs)
  468.         self.jobs = jobs
  469.         for fn, args in deferred_calls:
  470.             fn(*args)
  471.         
  472.         self.set_process_pending(True)
  473.         if not self.received_any_dbus_signals:
  474.             if self.update_timer:
  475.                 gobject.source_remove(self.update_timer)
  476.             
  477.             interval = 1000 * notifications['notify-get-interval']
  478.             self.update_timer = gobject.timeout_add(interval, self.get_notifications)
  479.         
  480.         return False
  481.  
  482.     
  483.     def refresh(self, which_jobs = None, refresh_all = True):
  484.         debugprint('refresh')
  485.         if which_jobs != None:
  486.             self.which_jobs = which_jobs
  487.         
  488.         user = cups.getUser()
  489.         
  490.         try:
  491.             cups.setUser(self.user)
  492.             c = cups.Connection(host = self.host, port = self.port, encryption = self.encryption)
  493.         except RuntimeError:
  494.             self.watcher.cups_connection_error(self)
  495.             cups.setUser(user)
  496.             return None
  497.  
  498.         if self.sub_id != -1:
  499.             
  500.             try:
  501.                 c.cancelSubscription(self.sub_id)
  502.             except cups.IPPError:
  503.                 (e, m) = None
  504.                 self.watcher.cups_ipp_error(self, e, m)
  505.  
  506.             if self.update_timer:
  507.                 gobject.source_remove(self.update_timer)
  508.             
  509.             debugprint('Canceled subscription %d' % self.sub_id)
  510.         
  511.         
  512.         try:
  513.             del self.sub_seq
  514.         except AttributeError:
  515.             pass
  516.  
  517.         events = [
  518.             'printer-added',
  519.             'printer-deleted',
  520.             'printer-state-changed']
  521.         if self.monitor_jobs:
  522.             events.extend([
  523.                 'job-created',
  524.                 'job-completed',
  525.                 'job-stopped',
  526.                 'job-state-changed'])
  527.         
  528.         
  529.         try:
  530.             self.sub_id = c.createSubscription('/', events = events)
  531.         except cups.IPPError:
  532.             (e, m) = None
  533.             self.watcher.cups_ipp_error(self, e, m)
  534.  
  535.         cups.setUser(user)
  536.         self.update_timer = gobject.timeout_add(MIN_REFRESH_INTERVAL * 1000, self.get_notifications)
  537.         debugprint('Created subscription %d' % self.sub_id)
  538.         if self.monitor_jobs:
  539.             jobs = self.jobs.copy()
  540.             if self.which_jobs not in ('all', 'completed'):
  541.                 filtered = { }
  542.                 for jobid, job in jobs.iteritems():
  543.                     if job['job-state'] < cups.IPP_JOB_CANCELED:
  544.                         filtered[jobid] = job
  545.                         continue
  546.                 
  547.                 jobs = filtered
  548.             
  549.             self.fetch_first_job_id = 1
  550.             if self.fetch_jobs_timer:
  551.                 gobject.source_remove(self.fetch_jobs_timer)
  552.             
  553.             self.fetch_jobs_timer = gobject.timeout_add(5, self.fetch_jobs, refresh_all)
  554.         else:
  555.             jobs = { }
  556.         
  557.         try:
  558.             self.printer_state_reasons = collect_printer_state_reasons(c)
  559.             dests = c.getPrinters()
  560.             self.printers = set(dests.keys())
  561.         except cups.IPPError:
  562.             (e, m) = None
  563.             self.watcher.cups_ipp_error(self, e, m)
  564.             return None
  565.             except RuntimeError:
  566.                 self.watcher.cups_connection_error(self)
  567.                 return None
  568.             elif self.specific_dests != None:
  569.                 for jobid in jobs.keys():
  570.                     uri = jobs[jobid].get('job-printer-uri', '/')
  571.                     i = uri.rfind('/')
  572.                     printer = uri[i + 1:]
  573.                     if printer not in self.specific_dests:
  574.                         del jobs[jobid]
  575.                         continue
  576.                 
  577.             
  578.  
  579.         self.set_process_pending(False)
  580.         self.watcher.current_printers_and_jobs(self, self.printers.copy(), jobs.copy())
  581.         self.update_jobs(jobs)
  582.         self.jobs = jobs
  583.         self.set_process_pending(True)
  584.         return False
  585.  
  586.     
  587.     def fetch_jobs(self, refresh_all):
  588.         if not self.process_pending_events:
  589.             return True
  590.         user = cups.getUser()
  591.         
  592.         try:
  593.             cups.setUser(self.user)
  594.             c = cups.Connection(host = self.host, port = self.port, encryption = self.encryption)
  595.         except RuntimeError:
  596.             self.process_pending_events
  597.             self.process_pending_events
  598.             self.watcher.cups_connection_error(self)
  599.             self.fetch_jobs_timer = None
  600.             cups.setUser(user)
  601.             return False
  602.  
  603.         limit = 1
  604.         
  605.         try:
  606.             fetched = c.getJobs(which_jobs = self.which_jobs, my_jobs = self.my_jobs, first_job_id = self.fetch_first_job_id, limit = limit)
  607.         except cups.IPPError:
  608.             self.process_pending_events
  609.             (e, m) = self.process_pending_events
  610.             self.watcher.cups_ipp_error(self, e, m)
  611.             self.fetch_jobs_timer = None
  612.             cups.setUser(user)
  613.             return False
  614.  
  615.         cups.setUser(user)
  616.         got = len(fetched)
  617.         debugprint('Got %s jobs, asked for %s' % (got, limit))
  618.         deferred_calls = []
  619.         jobs = self.jobs.copy()
  620.         jobids = fetched.keys()
  621.         jobids.sort()
  622.         if got > 0:
  623.             last_jobid = jobids[got - 1]
  624.         else:
  625.             last_jobid = self.fetch_first_job_id + limit
  626.         for jobid in xrange(self.fetch_first_job_id, last_jobid + 1):
  627.             
  628.             try:
  629.                 job = fetched[jobid]
  630.                 if self.specific_dests != None:
  631.                     uri = job.get('job-printer-uri', '/')
  632.                     i = uri.rfind('/')
  633.                     printer = uri[i + 1:]
  634.                     if printer not in self.specific_dests:
  635.                         raise KeyError
  636.                     printer not in self.specific_dests
  637.                 
  638.                 if jobs.has_key(jobid):
  639.                     fn = self.watcher.job_event
  640.                 else:
  641.                     fn = self.watcher.job_added
  642.                 jobs[jobid] = job
  643.                 deferred_calls.append((fn, (self, jobid, '', { }, job.copy())))
  644.             continue
  645.             except KeyError:
  646.                 if jobs.has_key(jobid):
  647.                     del jobs[jobid]
  648.                     deferred_calls.append((self.watcher.job_removed, (self, jobid, '', { })))
  649.                 
  650.                 jobs.has_key(jobid)
  651.             
  652.  
  653.         
  654.         jobids = jobs.keys()
  655.         jobids.sort()
  656.         if got < limit:
  657.             trim = False
  658.             for i in range(len(jobids)):
  659.                 jobid = jobids[i]
  660.                 if not trim and jobid > last_jobid:
  661.                     trim = True
  662.                 
  663.                 if trim:
  664.                     del jobs[jobid]
  665.                     deferred_calls.append((self.watcher.job_removed, (self, jobid, '', { })))
  666.                     continue
  667.             
  668.         
  669.         self.update_jobs(jobs)
  670.         self.jobs = jobs
  671.         for fn, args in deferred_calls:
  672.             fn(*args)
  673.         
  674.         if got < limit:
  675.             self.fetch_jobs_timer = None
  676.             return False
  677.         next = jobid + 1
  678.         while not refresh_all and self.jobs.has_key(next):
  679.             next += 1
  680.             continue
  681.             got < limit
  682.         self.fetch_first_job_id = next
  683.         return True
  684.  
  685.     
  686.     def sort_jobs_by_printer(self, jobs = None):
  687.         if jobs == None:
  688.             jobs = self.jobs
  689.         
  690.         my_printers = set()
  691.         printer_jobs = { }
  692.         for job, data in jobs.iteritems():
  693.             state = data.get('job-state', cups.IPP_JOB_CANCELED)
  694.             if state >= cups.IPP_JOB_CANCELED:
  695.                 continue
  696.             
  697.             uri = data.get('job-printer-uri', '')
  698.             i = uri.rfind('/')
  699.             if i == -1:
  700.                 continue
  701.             
  702.             printer = uri[i + 1:]
  703.             my_printers.add(printer)
  704.             if not printer_jobs.has_key(printer):
  705.                 printer_jobs[printer] = { }
  706.             
  707.             printer_jobs[printer][job] = data
  708.         
  709.         return (printer_jobs, my_printers)
  710.  
  711.     
  712.     def update_jobs(self, jobs):
  713.         debugprint('update_jobs')
  714.         (printer_jobs, my_printers) = self.sort_jobs_by_printer(jobs)
  715.         self.check_state_reasons(my_printers, printer_jobs)
  716.  
  717.     
  718.     def update(self):
  719.         if self.update_timer:
  720.             gobject.source_remove(self.update_timer)
  721.         
  722.         self.update_timer = gobject.timeout_add(200, self.get_notifications)
  723.  
  724.     
  725.     def handle_dbus_signal(self, *args):
  726.         self.update()
  727.         if not self.received_any_dbus_signals:
  728.             self.received_any_dbus_signals = True
  729.         
  730.  
  731.  
  732. if __name__ == '__main__':
  733.     set_debugging(True)
  734.     m = Monitor(Watcher())
  735.     loop = gobject.MainLoop()
  736.     
  737.     try:
  738.         loop.run()
  739.     finally:
  740.         m.cleanup()
  741.  
  742.  
  743.